package org.openea.eap.module.obpm.service.form.generator;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.openbpm.base.api.constant.IStatusCode;
import org.openbpm.base.api.exception.BusinessException;
import org.openbpm.base.core.i18n.I18nUtil;
import org.openbpm.base.core.util.StringUtil;
import org.openbpm.base.core.util.ThreadMapUtil;
import org.openbpm.bus.api.constant.BusColumnCtrlType;
import org.openbpm.bus.api.constant.BusTableRelType;
import org.openbpm.bus.api.model.IBusTableRel;
import org.openbpm.bus.api.model.IBusinessColumn;
import org.openbpm.form.api.constant.FormStatusCode;
import org.openea.eap.module.obpm.model.form.design.FormColumn;
import org.openea.eap.module.obpm.model.form.design.FormGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public abstract class AbsFormElementGenerator {
    protected Logger LOG = LoggerFactory.getLogger(getClass());


    public abstract String getGeneratorName();


    public String getColumn(IBusinessColumn column, IBusTableRel relation) {
        if (column == null) {
            throw new BusinessException(String.format("%s 生成表单异常，column 为 null", new Object[]{(relation != null) ? relation.getTableComment() : ""}));
        }
        String boCode = relation.getBusObj().getKey();
        ThreadMapUtil.put("boCode", boCode);
        ThreadMapUtil.put("relation", relation);

        if (column.getCtrl() == null) {
            this.LOG.debug(" column [{}]ctrl 配置为空，默认生成 input框，表：{}", column.getComment(), column.getTable().getComment());
            return getColumnOnetext(column);
        }

        BusColumnCtrlType columnType = BusColumnCtrlType.getByKey(column.getCtrl().getType());
        if (columnType == null) {
            this.LOG.debug(" column [{}]ctrl 类型{}为空，默认生成 input框，表：{}", column.getComment(), column.getCtrl().getType(), column.getTable().getComment());
            return getColumnOnetext(column);
        }

        try {
            switch (columnType) {
                case ONETEXT:
                    return getColumnOnetext(column);
                case DATE:
                    return getColumnDate(column);
                case DIC:
                    return getColumnDic(column);
                case SERIALNO:
                    return getColumnIdentity(column);
                case MULTITEXT:
                    return getColumnMultitext(column);
                case JSON:
                    return getColumnJson(column);
                case CHECKBOX:
                    return getColumnCheckBox(column);

                case RADIO:
                    return getColumnRadio(column);
                case SELECT:
                    return getColumnSelect(column, Boolean.valueOf(false));

                case PIC:
                    return getColumnPic(column);
                case MPIC:
                    return getColumnMPic(column);

                case FILE:
                    return getColumnFile(column);

//        case CITY:
//          return getColumnCitySelect(column);

                case SIGNATURE:
                    return getColumnSignature(column);
                case SCANCODE:
                    return getColumnScanCode(column);
            }
            return "";

        } catch (Exception e) {
            String columnTypeDesc = "";
            // fix columnType is null
            if (columnType != null) {
                columnTypeDesc = columnType.getDesc();
            }
            throw new BusinessException(String.format("表单字段 [%s-%s]解析失败 ,控件类型[%s] :%s", new Object[]{column.getTable().getName(), column.getComment(), columnTypeDesc, e.getMessage()}), (IStatusCode) FormStatusCode.FORM_ELEMENT_GENERATOR_ERROR, e);
        }
    }

    protected String getColumnCitySelect(IBusinessColumn column) {
        return "";
    }

    public String getColumn(FormGroup group, FormColumn formColumn) {
        IBusTableRel tableRel = group.getTableRelation();


        if (StringUtil.isNotEmpty(formColumn.getTableKey()) && !formColumn.getTableKey().equals(tableRel.getTableKey())) {
            IBusTableRel table = tableRel.find(formColumn.getTableKey());
            if (table != null) {
                tableRel = table;
            }
        }

        if (!formColumn.getTableKey().equals(tableRel.getTableKey())) {
            this.LOG.error("生成表单可能存在异常！formColumnTableKey{},tableRelTableKey{}", formColumn.getTableKey(), tableRel.getTableKey());
        }

        IBusinessColumn businessColumn = tableRel.getTable().getColumnByKey(formColumn.getKey());

        if (businessColumn == null) {
            this.LOG.error("布局模板查找Column配置失败！字段：{}，表：{}", formColumn.getComment(), formColumn.getTableKey());
        }

        return getColumn(businessColumn, tableRel);
    }


    protected abstract String getColumnOnetext(IBusinessColumn column);


    protected abstract String getColumnDate(IBusinessColumn column);


    protected abstract String getColumnDic(IBusinessColumn column);


    protected abstract String getColumnIdentity(IBusinessColumn column);


    protected abstract String getColumnMultitext(IBusinessColumn column);

    protected String getColumnJson(IBusinessColumn column) {
        return getColumnMultitext(column);
    }

    protected abstract String getColumnCheckBox(IBusinessColumn column);

    protected abstract String getColumnRadio(IBusinessColumn column);

    protected abstract String getColumnSelect(IBusinessColumn column, Boolean isMultiple);

    protected abstract String getColumnFile(IBusinessColumn column);

    protected String getColumnSignature(IBusinessColumn column) {
        return "暂时不支持该组件";
    }

    protected String getColumnScanCode(IBusinessColumn column) {
        return "暂时不支持该组件";
    }

    protected String getColumnPic(IBusinessColumn column) {
        // 单图
        return getColumnFile(column);
    }

    protected String getColumnMPic(IBusinessColumn column) {
        // 多图，默认同文件
        return getColumnFile(column);
    }

    protected Element getElement(String type) {
        Document doc = Jsoup.parse("");
        Element element = doc.createElement(type);
        return element;
    }


    protected void handlePermission(Element element, IBusinessColumn column) {
        element.attr("ab-basic-permission", getPermissionPath(column));
        element.attr("desc", column.getComment());
    }

    public String getPermissionPath(IBusinessColumn column, IBusTableRel relation) {
        String boCode = relation.getBusObj().getKey();
        return "permission." + boCode + "." + column.getTable().getKey() + "." + column.getKey();
    }

    protected String getPermissionPath(IBusinessColumn column) {
        String boCode = (String) ThreadMapUtil.get("boCode");
        return "permission." + boCode + "." + column.getTable().getKey() + "." + column.getKey();
    }

    protected String getModelPath(IBusinessColumn column) {
        String boCode = (String) ThreadMapUtil.get("boCode");
        IBusTableRel relation = (IBusTableRel) ThreadMapUtil.get("relation");

        if (relation.getType().equals(BusTableRelType.ONE_TO_MANY.getKey())) {
            return column.getTable().getKey() + "." + column.getKey();
        }

        return getScopePath(relation) + "." + column.getKey();
    }

    protected void handleValidateRules(Element element, IBusinessColumn column) {
        if (column.getCtrl() == null) {
            element.attr("ab-validate", "{}");

            return;
        }
        String rulesStr = column.getCtrl().getValidRule();
        JSONObject validateRule = new JSONObject();

        if (StringUtil.isNotEmpty(rulesStr)) {
            JSONArray rules = JSONArray.parseArray(rulesStr);


            for (int i = 0; i < rules.size(); i++) {
                JSONObject rule = rules.getJSONObject(i);

                validateRule.put(rule.getString("name"), Boolean.valueOf(true));
            }

            if (column.isRequired()) {
                validateRule.put("required", Boolean.valueOf(true));
            }
            if (column.getLength() > 1) {
                validateRule.put("maxlength", Integer.valueOf(column.getLength()));
            }
        }

        element.attr("ab-validate", validateRule.toJSONString());

        IBusTableRel relation = (IBusTableRel) ThreadMapUtil.get("relation");

        element.attr("desc", relation.getTableComment() + "-" + column.getComment());
    }

    public String getScopePath(IBusTableRel relation) {
        if (relation.getType().equals(BusTableRelType.MAIN.getKey())) {
            return "data." + relation.getBusObj().getKey();
        }

        StringBuilder sb = new StringBuilder();

        sb.append(relation.getTableKey());

        if (relation.getType().equals(BusTableRelType.ONE_TO_MANY.getKey())) {
            sb.append("List");

            if (isThreeChildren(relation)) {
                sb.insert(0, "subTempData.");
                return sb.toString();
            }
        }


        getParentPath(relation.getParent(), sb);

        return sb.toString();
    }

    protected void getParentPath(IBusTableRel parent, StringBuilder sb) {
        if (parent == null)
            return;
        if (parent.getType().equals(BusTableRelType.ONE_TO_MANY.getKey())) {
            sb.insert(0, parent.getTableKey() + ".");

            return;
        }
        if (parent.getType().equals(BusTableRelType.ONE_TO_ONE.getKey())) {
            sb.insert(0, parent.getTableKey() + ".");
        }

        if (parent.getType().equals(BusTableRelType.MAIN.getKey())) {
            sb.insert(0, "data." + parent.getBusObj().getKey() + ".");
        }

        getParentPath(parent.getParent(), sb);
    }

    public abstract String getSubAttrs(IBusTableRel paramIBusTableRel);

    public boolean isThreeChildren(IBusTableRel rel) {
        if (rel.getType().equals(BusTableRelType.ONE_TO_MANY.getKey()) &&
                !rel.getParent().getType().equals(BusTableRelType.MAIN.getKey())) {
            return true;
        }
        return false;
    }

    public String getDivVIf(IBusTableRel relation) {
        if (isThreeChildren(relation)) {
            return "v-if=\"subTempData." + relation.getParent().getTableKey() + "\"";
        }
        return "";
    }

    protected void handleElementPlaceHolder(IBusinessColumn column, Element element) {
        if (column.getCtrl() == null) {
            return;
        }
        String configStr = column.getCtrl().getConfig();
        if (StringUtil.isEmpty(configStr)) {
            return;
        }

        JSONObject config = JSON.parseObject(configStr);
        Boolean placeholder = config.getBoolean("placeholder");

        if (placeholder == null || !placeholder.booleanValue())
            return;
        element.attr("placeholder", config.getString("placeholderText"));
    }

    protected void checkCtrConfig(IBusinessColumn column, JSONObject config, String key) {
        if (column == null) {
            return;
        }
        if (config == null) {
            config = JSON.parseObject(column.getCtrl().getConfig());
        }
        if (config == null || (key != null && !config.containsKey(key))) {
            //throw new BusinessException(String.format("表【%s】日期字段  【%s】解析失败,配置信息不能为空", new Object[]{column.getTable().getKey(), column.getComment()}));
            String ctrlType = I18nUtil.t("busColumnCtrlType." + column.getCtrl().getType(), column.getCtrl().getType());
            String msg = I18nUtil.t("form.generator.column.configIsNull", "Table %s Column %s Ctrl %s parse fail, config %s can not is null");
            throw new BusinessException(String.format(msg, new Object[]{column.getTable().getKey(), column.getComment(), ctrlType, key == null ? "" : key}));
        }
    }
}
